package utils

import (
	"context"
	"fmt"
	"runtime"
	"strconv"
	"time"

	"github.com/pkg/errors"
	"google.golang.org/grpc/peer"
	"hundsun.com/hsl/hschain/rpc/common/rpcerror"
	"hundsun.com/hsl/hschain/store/mq"

	"net"
	"reflect"
)

//Uint642Str Uint642Str
func Uint642Str(val uint64) string {
	return strconv.FormatUint(val, 10)
}

//Int642Str Int642Str
func Int642Str(val int64) string {
	return strconv.FormatInt(val, 10)
}

//Str2Uint64 Str2Uint64
func Str2Uint64(val string) (uint64, error) {
	return strconv.ParseUint(val, 10, 64)
}

//Invoke 反射调用
func Invoke(f interface{}, params []interface{}) []reflect.Value {
	fv := reflect.ValueOf(f)
	realParams := make([]reflect.Value, len(params)) //参数
	for i, item := range params {
		realParams[i] = reflect.ValueOf(item)
	}
	//panic拦截
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println(err)
		}
	}()
	rs := fv.Call(realParams)
	return rs
}

//GetClientIP context中获取ip
func GetClientIP(ctx context.Context) (string, error) {
	pr, ok := peer.FromContext(ctx)
	if !ok {
		return "", rpcerror.Errorf("[getClientIP] invoke FromContext() failed")
	}
	if pr.Addr == net.Addr(nil) {
		return "", fmt.Errorf("[getClientIP] peer.Addr is nil")
	}
	return pr.Addr.String(), nil
}

//FunName 获取当前方法名
func FunName() string {
	pc := make([]uintptr, 1)
	runtime.Callers(2, pc)
	f := runtime.FuncForPC(pc[0])
	return f.Name()
}

//SendMqRequestWithResp mq同步请求
func SendMqRequestWithResp(client mq.Client, mainTopic, subTopic string, ty int64, data interface{}, reqTimeOut time.Duration) (*mq.Message, error) {
	if client == nil {
		return nil, errors.Errorf("mq client is nil")
	}
	reqMsg := client.NewMessage(mainTopic, subTopic, ty, data)
	err := client.SendTimeout(reqMsg, true, reqTimeOut)
	if err != nil {
		return nil, err
	}

	resp, err := client.WaitTimeout(reqMsg, reqTimeOut)
	if err != nil {
		return nil, err
	}
	return resp, nil
}

//SendMqRequest mq异步请求
func SendMqRequest(client mq.Client, mainTopic, subTopic string, ty int64, data interface{}) error {
	reqMsg := client.NewMessage(mainTopic, subTopic, ty, data)
	err := client.Send(reqMsg, false)
	if err != nil {
		return err
	}
	return nil
}
